/**
* Copyright (c) By zengqh.
*
* This program is just for fun or demo, in the hope that it  
* will be useful, you can redistribute it and/or modify freely.
*
* Time: 2013/03/15
* File: Mesh.cpp
* Blog: http://www.cnblogs.com/zengqh/
**/

#include "Mesh.h"
#include "MeshMorphTarget.h"

namespace HY
{

Mesh::~Mesh()
{
	
}

MeshManager* Mesh::getMeshManager() const
{
	return 0;
}

uint32 Mesh::getNumOfLODLevels() const
{
	return lod_levels_.size();
}

MeshLODLevel* Mesh::addLODLevel()
{
	MeshLODLevel* lod_level = new MeshLODLevel(this);
	lod_levels_.push_back(lod_level);

	return lod_level;
}

MeshLODLevel* Mesh::GetLODLevel(uint32 nLODLevel) const
{
	return lod_levels_[nLODLevel];
}

uint32 Mesh::getNumOfMaterials() const
{
	return mat_list_.size();
}

Material* Mesh::addMaterial(Material *pMaterial)
{
	if (!pMaterial)
	{
		return;
	}

	for (uint32 i = 0; i < mat_list_.size(); ++i)
	{
		if (mat_list_[i] == pMaterial)
		{
			return pMaterial;
		}
	}

	mat_list_.push_back(pMaterial);
}

bool Mesh::deleteMaterial(uint32 nMaterial)
{
	Material* mat = mat_list_[nMaterial];

	if (mat)
	{
		for (uint32 i = 0; i < getNumOfLODLevels(); ++i)
		{
			const MeshLODLevel* lv = GetLODLevel(i);

			const std::vector<Geometry>* geo_list = lv->getGeometries();

			for (uint32 nGeo = 0; nGeo < geo_list->size(); ++nGeo)
			{
				Geometry& geo = (*geo_list)[nGeo];

				if (geo.getMaterial() == nMaterial)
				{
					geo.setMaterial(0);
				}

				if (geo.getMaterial() > nMaterial)
				{
					geo.setMaterial(geo.getMaterial() - 1);
				}
			}
		}

		HY_SAFE_DELETE(mat);
		mat_list_.erase(mat_list_.begin() + nMaterial);

		return true;
	}

	return false;
}

Material* Mesh::getMaterial(uint32 nMaterial) const
{
	return mat_list_[nMaterial];
}

bool Mesh::setMaterial(uint32 nMaterial, Material *pMaterial)
{
	mat_list_[nMaterial] = pMaterial;

	return true;
}

uint32 Mesh::getMaterialUsage(uint32 mat) const
{
	Material* mat = mat_list_[mat];

	uint32 usage = 0;
	if (mat)
	{
		for (uint32 i = 0; i < getNumOfLODLevels(); ++i)
		{
			const MeshLODLevel* lv = GetLODLevel(i);

			const std::vector<Geometry>* geo_list = lv->getGeometries();

			for (uint32 nGeo = 0; nGeo < geo_list->size(); ++nGeo)
			{
				Geometry& geo = (*geo_list)[nGeo];

				if (geo.getMaterial() == mat)
				{
					usage++;
				}
			}
		}
	}

	return usage;
}

bool Mesh::calculateNormals()
{
	return false;
}

bool Mesh::calculateTangentSpaceVectors()
{
	return false;
}

void Mesh::getBoundingBox(Vector3& vmin, Vector3& vmax)
{
	vmin = vmin_;
	vmax = vmax_;
}

void Mesh::setBoundingBox(const Vector3& vmin, const Vector3& vmax)
{
	vmin_ = vmin;
	vmax_ = vmax;
}

bool Mesh::calculateBoundingBox(Vector3& vmin, Vector3& vmax)
{
	return false;
}

bool Mesh::calculateBoundingSphere(Vector3& pos, float& radius)
{
	return false;
}

Mesh::Mesh(RenderSystem* render_sys, const std::string& name)
: render_sys_(render_sys)
, name_(name)
{
	
}

}